package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.HotArticleService;
import com.heima.feigns.admin.AdminFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vo.HotArticleVo;
import com.heima.model.common.constants.ArticleConstants;
import com.heima.model.common.dtos.ResponseResult;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Version: V1.0
 */
@Service
@Transactional
public class HotArticleServiceImpl implements HotArticleService {

    @Autowired
    ApArticleService apArticleService;

    @Autowired
    AdminFeign adminFeign;

    @Autowired
    StringRedisTemplate redisTemplate;
    /**
     * 定时任务
     * 计算前五天的有热度的文章
     * 计算完成后把该五篇文章的flag设置为1
     */
    @Override
    public void computeHotArticle() {
        //1.查询所有的文章
        String date = DateTime.now().minusDays(5).toString("yyyy-MM-dd 00:00:00");
        List<ApArticle> list = apArticleService.list(Wrappers.<ApArticle>lambdaQuery().gt(ApArticle::getPublishTime, date));
        //2.计算所有文章的得分
        List<HotArticleVo> scoreList=countAllScore(list);
        //3.根据目前的得分情况 为每一个频道缓存热点较高的30条文章
        countAndCacheRedis(scoreList);
    }

    private void countAndCacheRedis(List<HotArticleVo> scoreList) {
        //存入综合的redis缓存中去
        List<HotArticleVo> list = scoreList.stream().
                sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());

        //遍历list集合把应当存入redis缓存中的文章flag设置为1
        list.stream().limit(5).forEach(articleFlag->{
            articleFlag.setFlag((byte)1);
            apArticleService.updateById(articleFlag);
        });


        redisTemplate.opsForValue().set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + ArticleConstants.DEFAULT_TAG,
                JSON.toJSONString(list));

        //根據不同的频道,存入不同的redis緩存中去
        ResponseResult result = adminFeign.findAll();
        if(result.getCode()!=0){
            return;
        }

        List<AdChannel> channels= JSON.parseArray(JSON.toJSONString(result.getData()), AdChannel.class);
        if (channels==null||channels.size()==0){
            return;
        }
        for (AdChannel adChannel : channels) {
            List<HotArticleVo> hotArticleVos = scoreList.stream()
                    .filter(hotArticle -> hotArticle.getChannelId().equals(adChannel.getId()))
                    .collect(Collectors.toList());
            List<HotArticleVo> channelList = hotArticleVos.stream().
                    sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).limit(5).collect(Collectors.toList());

            channelList.stream().limit(5).forEach(articleFlag->{
                articleFlag.setFlag((byte)1);
                apArticleService.updateById(articleFlag);
            });

            redisTemplate.opsForValue().set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + adChannel.getId(),
                    JSON.toJSONString(channelList));
        }

    }

    /**
     * 计算所有文章的分值并返回
     * @param list
     * @return
     */
    private List<HotArticleVo> countAllScore(List<ApArticle> list) {
        List<HotArticleVo> scoreList=new ArrayList();
        list.stream().forEach(
                apArticle -> {
                    //计算每一个的得分
                    HotArticleVo hotArticleVo=countEveryScore(apArticle);
                    BeanUtils.copyProperties(apArticle,hotArticleVo);
                    scoreList.add(hotArticleVo);
                }
        );
        return scoreList;
    }

    private HotArticleVo countEveryScore(ApArticle apArticle) {
        HotArticleVo articleVo=new HotArticleVo();
        int score = 0;
        // 阅读 1
        if (apArticle.getViews() != null) {
            score += apArticle.getViews() * ArticleConstants.HOT_ARTICLE_VIEW_WEIGHT;
        }
        // 点赞 3
        if (apArticle.getLikes() != null) {
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        // 评论 5
        if (apArticle.getComment() != null) {
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        // 收藏 8
        if (apArticle.getCollection() != null) {
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }

        articleVo.setScore(score);
        return articleVo;
    }
}